﻿using Common.Communication;
using Common.Device.DeviceDb;
using Common.Device.Interfaces;
using Common.Tool.DataTools;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ZhiKong
{
    public class N110ZSerialPort : SerialPortBase, IZhiKong
    {
        public string Name { get; set; }
        byte Addr;
        public N110ZSerialPort(UseDevice device) : base(device.port, Convert.ToInt32(device.parameter), timeout: 1500)
        {
            Name = device.name;
            Addr = Convert.ToByte(device.addr);
        }

        
        byte[] CmdRead0(uint cmd, uint ops, ulong data, uint reserve1, uint reserve2, uint reserve3)
        {
            byte[] dataBytes1 = new byte[] { 0x5A, 0x5A, 0x5A, 0x5A };
            byte[] dataBytes2 = BitConverter.GetBytes(cmd);
            byte[] dataBytes3 = BitConverter.GetBytes(ops);
            byte[] dataBytes4 = BitConverter.GetBytes(data);
            byte[] combined = new byte[24];
            dataBytes1.CopyTo(combined, 0);
            dataBytes2.CopyTo(combined, 4);
            dataBytes3.CopyTo(combined, 8);
            dataBytes4.CopyTo(combined, 12);
            combined[20]= Convert.ToByte(reserve1);
            combined[21]= Convert.ToByte(reserve2);
            combined[22]= Convert.ToByte(reserve3);
            combined[23]= CalculateChecksum(combined);
            return combined;
        }
        public byte CalculateChecksum(byte[] data)
        {
            if (data == null || data.Length < 19)
                throw new ArgumentException("数据长度不足19字节");

            int sum = 0;
            for (int i = 0; i < 19; i++)
            {
                sum += data[i];
            }
            return (byte)(sum % 256);
        }
        public bool ValidateChecksum(byte[] receivedData)
        {

            // 计算前19字节的和
            int sum = 0;
            for (int i = 0; i < 23; i++)
            {
                sum += receivedData[i];
            }

            // 取模后与第20字节（校验和）比较
            byte calculatedChecksum = (byte)(sum % 256);
            return receivedData[23] == calculatedChecksum;
        }
        public string jiaoyan(byte[] send, byte[] receivedData)
        {
            if (receivedData == null || receivedData.Length == 0)
            {
                return "无信息";
            }
            if (receivedData.Length!=24)
            {
                return "长度错误";
            }
            if (!ValidateChecksum(receivedData))
            {
                return "校验和错误错误";
            }
            for (int i = 0; i<4; i++)
            {

                if (send[i]!=receivedData[i])
                {
                   
                        return "表头错误";
                }
            }
            return "OK";
        }

        public Result<string[]> ReadSensor0(uint cmd, uint ops, ulong data, uint reserve1, uint reserve2, uint reserve3, int channel = 1)
        {
            lock (this)
            {
                localPort.ReadTimeout=1000;
                var result = new Result<string[]>();
                var write = new Result<byte[]>();
                byte[] bytes = new byte[2];
                var read = new Result<byte[]>();
                string[] vsla = new string[3];
                AppendInfo(Name, $"接收开机命令");
                //var command = CmdRead0(cmd, ops, data,reserve1,reserve2, reserve3);
                //write = WriteThenRead(command, wait: 100);
                write =ReadBytes();
                if (!write.IsSucceed )
                {
                    result.IsSucceed = false;
                    result.Err = "接收开机命令通信失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                byte[] dataBytes1 = new byte[] { 0x5A, 0x5A, 0x5A, 0x5A };
                string retul = jiaoyan(dataBytes1, write.Value);
                if (retul!="OK")
                {
                    result.IsSucceed = false;
                    result.Err = retul;
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                uint cmd1 = BitConverter.ToUInt32(write.Value, 4);
                vsla[0] = cmd1.ToString();
                // 3. 解析OPS（字节8-11）
                uint ops1 = BitConverter.ToUInt32(write.Value, 8);
                vsla[1] = ops1.ToString();

                // 4. 解析Data（字节12-15）
                ulong data1 = BitConverter.ToUInt64(write.Value, 12);
                vsla[2] = data1.ToString();
                result.Value=vsla;
                return result.EndTime();
            }
        }

        public Result<string[]> ReadSensor1(uint cmd, uint ops, ulong data, uint reserve1, uint reserve2, uint reserve3, int channel = 1)
        {
            lock (this)
            {
                localPort.ReadTimeout=5000;
                var result = new Result<string[]>();
                var write = new Result<byte[]>();
                byte[] bytes = new byte[2];
                byte[] datas = new byte[8];
                var read = new Result<byte[]>();
                string[] vsla = new string[3];
                AppendInfo(Name, $"自动测试");
                var command = CmdRead0(cmd, ops, data, reserve1, reserve2, reserve3);
                write = WriteThenRead(command, wait: 100);

                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "自动测试通信失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                string retul = jiaoyan(command, write.Value);
                if (retul!="OK")
                {
                    result.IsSucceed = false;
                    result.Err = retul;
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                uint cmd1 = BitConverter.ToUInt32(write.Value, 4);
                vsla[0] = cmd1.ToString();
                // 3. 解析OPS（字节8-11）
                uint ops1 = BitConverter.ToUInt32(write.Value, 8);
                vsla[1] = ops1.ToString();

                // 4. 解析Data（字节12-15）
                ulong data1 = BitConverter.ToUInt64(write.Value, 12);
                vsla[2] = data1.ToString();
                //Array.Copy(write.Value, 12, datas, 0, 8);
                //Array.Reverse(datas);
                //vsla[2] = DataConvert.ByteArrayToString(datas);
                result.Value=vsla;
                return result.EndTime();
            }
        }

        public Result<string> ReadSensor2(uint cmd, uint ops, ulong data, uint reserve1, uint reserve2, uint reserve3, int channel = 1)
        {
            lock (this)
            {
                localPort.ReadTimeout=5000;
                var result = new Result<string>();
                var write = new Result<byte[]>();
                byte[] bytes = new byte[2];
                var read = new Result<byte[]>();
                string[] vsla = new string[3];
                AppendInfo(Name, $"自动测试");
                var command = CmdRead0(cmd, ops, data, reserve1, reserve2, reserve3);
                result = (Result<string>)Write(command);
                return result.EndTime();
            }
        }

        public Result<string> ReadSensor3(uint cmd, uint ops, ulong data, uint reserve1, uint reserve2, uint reserve3, int channel = 1)
        {
            lock (this)
            {
                localPort.ReadTimeout=5000;
                var result = new Result<string>();
                var write = new Result<byte[]>();
                byte[] bytes = new byte[2];
                var read = new Result<byte[]>();
                string[] vsla = new string[3];
                AppendInfo(Name, $"自动测试");
                var command = CmdRead0(cmd, ops, data, reserve1, reserve2, reserve3);
                result = (Result<string>)Write(command);
                return result.EndTime();
            }
        }

        public Result<string[]> ReadSensor4(uint cmd, uint ops, ulong data, uint reserve1, uint reserve2, uint reserve3, int channel = 1)
        {
            lock (this)
            {
                localPort.ReadTimeout=5000;
                var result = new Result<string[]>();
                var write = new Result<byte[]>();
                byte[] bytes = new byte[2];
                byte[] datas = new byte[8];
                var read = new Result<byte[]>();
                string[] vsla = new string[3];
                AppendInfo(Name, $"自动测试");
                var command = CmdRead0(cmd, ops, data, reserve1, reserve2, reserve3);
                write = WriteThenRead(command, wait: 100);

                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "自动测试通信失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                string retul = jiaoyan(command, write.Value);
                if (retul!="OK")
                {
                    result.IsSucceed = false;
                    result.Err = retul;
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                uint cmd1 = BitConverter.ToUInt32(write.Value, 4);
                vsla[0] = cmd1.ToString();
                // 3. 解析OPS（字节8-11）
                uint ops1 = BitConverter.ToUInt32(write.Value, 8);
                vsla[1] = ops1.ToString();

                // 4. 解析Data（字节12-15）
                ulong data1 = BitConverter.ToUInt64(write.Value, 12);
                //vsla[2] = data1.ToString();
                Array.Copy(write.Value, 12, datas, 0, 8);
                Array.Reverse(datas);
                vsla[2] = DataConvert.ByteArrayToString(datas);
                result.Value=vsla;
                return result.EndTime();
            }
        }
        public Result<string> ReadSensor5(uint cmd, uint ops, ulong data, uint reserve1, uint reserve2, uint reserve3, int channel = 1)
        {
            throw new NotImplementedException();
        }
        public Result<string> ReadSensor6(uint cmd, uint ops, ulong data, uint reserve1, uint reserve2, uint reserve3,int timenumber, int channel = 1)
        {
            lock (this)
            {
                localPort.ReadTimeout=5000;
                var result = new Result<string>();
                var write = new Result<byte[]>();
                byte[] bytes = new byte[2];
                var read = new Result<byte[]>();
                string[] vsla = new string[3];
                AppendInfo(Name, $"接收开机命令");
                DateTime beginTime = DateTime.Now;
                //var command = CmdRead0(cmd, ops, data,reserve1,reserve2, reserve3);
                //write = WriteThenRead(command, wait: 100);
                byte[] dataBytes1 = new byte[] { 0x5A, 0x5A, 0x5A, 0x5A };
                while (true)
                {
                    TimeSpan elapsed = DateTime.Now - beginTime;
                    int milliseconds = (int)elapsed.TotalSeconds;
                    //int milliseconds = (int)elapsed.TotalMilliseconds;
                    if (milliseconds>timenumber)
                    {
                        result.IsSucceed = true;
                        result.Err = "未接收信息，模式切换";
                        AppendTip(Name, result.Err);
                        return result.EndTime();
                    }
                    write =ReadBytes(); 
                    if (!write.IsSucceed)
                    {
                        if (write.Err=="返回超时")
                        {
                            continue;
                        }
                        result.IsSucceed = false;
                        result.Err = "接收开机命令通信失败";
                        AppendTip(Name, result.Err);
                        return result.EndTime();
                    }
                    string retul = jiaoyan(dataBytes1, write.Value);
                    if (retul=="OK")
                    {
                        result.IsSucceed = false;
                        result.Err = "检查到有效帧表头模式切换失败";
                        AppendTip(Name, result.Err);
                        return result.EndTime();
                    }
                }
                return result.EndTime();
            }
        }
    }
}
